{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "solidpysimp.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "include_colab_link": true
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.3"
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/jumbojing/ViewSCAD/blob/master/solidpysimp.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dm1CV45MrMzH",
        "colab_type": "text"
      },
      "source": [
        "# SolidPython -- 在Python里应用Openscad软件实现3D建模\\n(修改简化版）\n",
        "\n",
        "\n",
        "- --form https://github.com/SolidCode/SolidPython\n",
        "\n",
        "> 参考[Parkinbot](https://www.thingiverse.com/Parkinbot/about)[shortcuts.scad](https://www.thingiverse.com/download:4599227)做了部分修改使得代码更为简洁易读\n",
        "\n",
        "\n",
        "> 以下是对solidpython的[readme](https://github.com/SolidCode/SolidPython/blob/master/README.rst)的学习笔记(其中的部分code进行了简化)：\n",
        "\n",
        "> --好像作者是在这个[链接](http://www.thingiverse.com/thing:1481)中得到启发，下面是个例子：\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1lRWP6p-rMzK",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from solid import *\n",
        "d = difference()(\n",
        "    Cu(10),\n",
        "    Sp(15)\n",
        ")\n",
        "print(scad_render(d))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0d09QrXorMzW",
        "colab_type": "text"
      },
      "source": [
        "这个改变似乎没啥意思呀，继续往下看："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "W1Bochf9rMza",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from solid import *\n",
        "from solid.utils import *\n",
        "import viewscad\n",
        "import os\n",
        "import sys\n",
        "\n",
        "r = viewscad.Renderer()\n",
        "\n",
        "SEGMENTS = 60\n",
        "d = Sec()\n",
        "\n",
        "r.render(d)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Bi6uAtqxrMzm",
        "colab_type": "text"
      },
      "source": [
        "这是OpenSCAD代码:\n",
        "\n",
        "<pre>\n",
        "difference(){\n",
        "    union(){\n",
        "        cube(5);\n",
        "        translate( [5, 0,0]){\n",
        "            sphere(5);\n",
        "        }\n",
        "    }\n",
        "    cylinder(r=2, h=6);\n",
        "}\n",
        "</pre>\n",
        "\n",
        "    比原来的编码简单易读，好聪明的方法！\n",
        "    \n",
        "    当然了，还可以应用Python实现更多的可能：\n",
        "\n",
        "    > 内置字典类型\n",
        "\n",
        "    > 可变，可切片的列表和字符串类型\n",
        "\n",
        "    > 递归\n",
        "\n",
        "    > 外部库（图像！3D几何！网页抓取！...）\n",
        "\n",
        "### 安装方法：\n",
        "\n",
        "1. 直接pip：\n",
        "\n",
        "    <pre>\n",
        "    pip install solidpython\n",
        "    </pre>\n",
        "    \n",
        "2. [下载](https://github.com/SolidCode/SolidPython/archive/master.zip)(或者直接克隆)并解压,并在解压目录内安装:\n",
        "        <pre>\n",
        "        python setup.py install\n",
        "        </pre>\n",
        "        \n",
        "### 加入简化码的方法：\n",
        "\n",
        "* 在\\solid\\objects.py文件的最后粘贴以下代码：\n",
        "\n",
        "\n",
        "> Ci= circle #圆\n",
        ">\n",
        "> Sq= square #方\n",
        ">\n",
        "> Sp= sphere #(radius | d=diameter) 球\n",
        ">\n",
        "> Cu= cube #(size, center) or cube([width,depth,height], center) 立方\n",
        ">\n",
        "> Cy= cylinder #(h,r|d,center) or cylinder(h,r1|d1,r2|d2,center) 锥柱\n",
        ">\n",
        "> Mi= mirror #镜像\n",
        ">\n",
        "> Of = offset # 偏移\n",
        ">\n",
        "> C= color #色\n",
        ">\n",
        "> Le= linear_extrude #(height,center,convexity,twist,slices,scale) 线拖\n",
        ">\n",
        "> Re= rotate_extrude #(angle,convexity) 旋拖\n",
        ">\n",
        "> dxf_Le=  dxf_linear_extrude #dxf拖\n",
        ">\n",
        "> Pr= projection #(cut) 投影\n",
        ">\n",
        "> Sf= surface #(file = \"….dat\",center,convexity)\n",
        ">\n",
        "> deb= debug ##\n",
        ">\n",
        "> bac= background # !\n",
        ">\n",
        "> roo= root # %\n",
        ">\n",
        "> dis= disable # *\n",
        "\n",
        "* 在\\solid\\utils.py同样：\n",
        "\n",
        "> \n",
        "> \\# 旋转和移动\n",
        "> \n",
        "> def Tx(x):\n",
        ">     return translate([x,0,0])\n",
        "> \n",
        "> \n",
        "> def Ty(y):\n",
        ">     return translate([0,y,0])\n",
        "> \n",
        "> \n",
        "> def Tz(z):\n",
        ">     return translate([0,0,z])\n",
        "> \n",
        "> \n",
        "> def Rx(x=90):\n",
        ">     return rotate([x,0,0])\n",
        "> \n",
        "> \n",
        "> def Ry(y=90):\n",
        ">     return rotate([0,y,0])\n",
        "> \n",
        "> \n",
        "> def Rz(z=90):\n",
        ">     return rotate([0,0,z])\n",
        "> \n",
        ">     \n",
        "\n",
        "        \n",
        "### 使用方法：        \n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "U9Oy76KWrMzo",
        "colab_type": "text"
      },
      "source": [
        "* 导入模块"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RibWyx9FrMzq",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "    from solid import *\n",
        "    from solid.utils import *  # Not required, but the utils module is useful--非必须但是很有用\n",
        "    \n",
        "    import os\n",
        "    import sys\n",
        "    "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2wcKc0mXrMzy",
        "colab_type": "text"
      },
      "source": [
        "* 可以调用use和include模块，如下：(也不知道为啥老是出错）\n",
        "\n",
        "> use(\"/path/to/scadfile.scad\")\n",
        "\n",
        "> include(\"/path/to/scadfile.scad\")\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "c8WyEAUPrMz1",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "use(r\"C:\\Program Files\\OpenSCAD\\libraries\\shortcuts.scad\")# 为啥出错呀？"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wxNQotBHrM0A",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "use (r\"C:\\Users\\Administrator\\Documents\\3dguide\\testd.scad\")这个就行！！！"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-27PC8oFrM0M",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "    d = Cu(10) - Sp(15)\n",
        "    scad_render_to_file(d,r\"C:\\Users\\Administrator\\Documents\\3dguide\\testd.scad\")"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F5zlAoCHrM0Y",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "* **scad_render(py_scad_obj)** 返回OpenScad代码\n",
        "\n",
        "* **scad_render_to_file(py_scad_obj, filepath)** 另存为.scad文件\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PESg4RjRrM0e",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "    d = Cu(10) - Sp(15)\n",
        "    scad_render_to_file(d,r\"C:\\Users\\Administrator\\Documents\\3dguide\\testd.scad\")"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lDuwywOrrM0t",
        "colab_type": "text"
      },
      "source": [
        "* 这个命令还可以在OpenSCAD IDE中加载并预览编辑的图像（需要设置)\n",
        "\n",
        "* 还可以调用openscad的命令行格式可以直接导出为stl文件\n",
        "\n",
        "### 几个例子\n",
        "\n",
        "可以用如下代码打开例子的目录："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VAuVH2FZrM0y",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import os, solid; print(os.path.dirname(solid.__file__) + '\\examples')#例子在这里"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "W1AvnSAarM0_",
        "colab_type": "text"
      },
      "source": [
        "原链接：[here](https://github.com/SolidCode/SolidPython/tree/master/solid/examples)\n",
        "\n",
        "[solid/examples/solidpython_template.py](https://github.com/SolidCode/SolidPython/blob/master/solid/examples/solidpython_template.py)\n",
        "这是模板文件"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "FUcjtjpurM1D",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#! /usr/bin/env python\n",
        "# -*- coding: utf-8 -*-\n",
        "from __future__ import division#1.在python2 中导入未来的支持的语言特征中division(精确除法)，即from __future__ import division ，当我们在程序中没有导入该特征时，\"/\"操作符执行的只能是整除，也就是取整数，只有当我们导入division(精确算法)以后，\"/\"执行的才是精确算法。2.但是在python3中已经支持了精确算法，所以无需再导入division(精确算法)：\n",
        "import os\n",
        "import sys\n",
        "\n",
        "# Assumes SolidPython is in site-packages or elsewhwere in sys.path\n",
        "from solid import *\n",
        "from solid.utils import *\n",
        "\n",
        "SEGMENTS = 48\n",
        "\n",
        "\n",
        "def assembly():\n",
        "    # Your code here!在这里输入代码？这是个assembly函数还不懂啥意思以后在研究吧\n",
        "    a = union()\n",
        "\n",
        "    return a\n",
        "\n",
        "if __name__ == '__main__':\n",
        "    a = assembly()\n",
        "    scad_render_to_file(a, file_header='$fn = %s;' % SEGMENTS, include_orig_code=True)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cCtBQ5pprM1K",
        "colab_type": "text"
      },
      "source": [
        "### 句法彩蛋\n",
        "\n",
        "* 应用 **+ 表示合集，- 表示差集，* 表示交集** 很有创意，如下："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3lSXknfarM1N",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "c = Cy(r=10, h=5) + Cy(r=2, h=30)\n",
        "\n",
        "r.render(c)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "doQfUKnDrM1T",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ypnVSP6wrM1e",
        "colab_type": "text"
      },
      "source": [
        "* 还有这种方式："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "5NOM-5FFrM1g",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "c = Cy(r=10, h=5)\n",
        "c -= Cy(r=2, h=30)\n",
        "\n",
        "r.render(c)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uoiJ_geyrM1n",
        "colab_type": "text"
      },
      "source": [
        "* 还有个打洞的模块："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wPmi9N-DrM1q",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "outer = Cy(5, 30)\n",
        "inner = Cy(3,35)\n",
        "pipe_a = outer - hole()(inner)\n",
        "\n",
        "r.render(pipe_a)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZhBZ7OK0rM13",
        "colab_type": "text"
      },
      "source": [
        "* 这里提到了一个 part() 函数，以利于组装以后再看吧\n",
        "\n",
        "* **See solid/examples/animation_example.py** 动画模块。。。以后再看吧\n",
        "\n",
        "### solid.utils 这个模块还有一些有用的功能：\n",
        "\n",
        "[solid/utils.py](https://github.com/SolidCode/SolidPython/blob/master/solid/utils.py).\n",
        "比如：\n",
        "\n",
        "## 移动(translate)和旋转(rotate)的简化\n",
        "\n",
        "Directions: (up, down, left, right, forward, back) for arranging things:--作者自定义的方向函数，我做了了一些修改：\n",
        "\n",
        "- Tx(x)(py_scad_obj)\n",
        "- Ty(y)(py_scad_obj)\n",
        "- Tz(z)(py_scad_obj)\n",
        "- Rx(x=90)(py_scad_obj)\n",
        "- Ry(y=90)(py_scad_obj)\n",
        "- Rz(z=90)(py_scad_obj)\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "scrolled": false,
        "id": "0WhKL5kHrM19",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "b = Tx(5)(Cu(5))\n",
        "\n",
        "r.render(b)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zpV1C-XfrM2H",
        "colab_type": "text"
      },
      "source": [
        "### 还有一个打洞的模块"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "utPx0JQprM2K",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "outer = Cy(5, 30)\n",
        "inner = Cy(3,35)\n",
        "pipe_a = outer - hole()(inner)\n",
        "\n",
        "r.render(pipe_a)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sXsXEA-3rM2f",
        "colab_type": "text"
      },
      "source": [
        "这里[solid/examples/hole_example.py](https://github.com/SolidCode/SolidPython/blob/master/solid/examples/hole_example.py)有一个示范文件，分段分析一下。。。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ovWm55tQrM2k",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#! /usr/bin/env python\n",
        "# -*- coding: utf-8 -*-\n",
        "from __future__ import division\n",
        "import os\n",
        "import sys\n",
        "\n",
        "# Assumes SolidPython is in site-packages or elsewhwere in sys.path\n",
        "from solid import *\n",
        "from solid.utils import *\n",
        "\n",
        "SEGMENTS = 120#相当于fn"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WY7WxON7rM23",
        "colab_type": "text"
      },
      "source": [
        "- 通过hole()声明负空间，这个管子的内部总是空的，即使将两个交叉合并"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "i0JhuHtarM2_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def pipe_intersection_hole():\n",
        "    pipe_od = 12\n",
        "    pipe_id = 10\n",
        "    seg_length = 30\n",
        "\n",
        "    outer = Cy(r=pipe_od, h=seg_length, center=True)\n",
        "    inner = Cy(r=pipe_id, h=seg_length + 2, center=True)\n",
        "\n",
        "    # By declaring that the internal void of pipe_a should\n",
        "    # explicitly remain empty, the combination of both pipes\n",
        "    # is empty all the way through.\n",
        "    # -通过hole()声明负空间，这个管子的内部总是空的，即使将两个\n",
        "    # -交叉合并\n",
        "\n",
        "    # Any OpenSCAD / SolidPython object can be declared a hole(),\n",
        "    # and after that will always be empty\n",
        "    pipe_a = outer + hole()(inner)\n",
        "    # Note that \"pipe_a = outer - hole()(inner)\" would work identically;\n",
        "    # inner will always be subtracted now that it's a hole\n",
        "\n",
        "    pipe_b = Ry()(pipe_a)\n",
        "    return pipe_a + pipe_b\n",
        "\n",
        "r.render(pipe_intersection_hole())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xQ2XjNhIrM3O",
        "colab_type": "text"
      },
      "source": [
        "- 不用hole()就是这个结果"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1Qb1CJahrM3S",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def pipe_intersection_no_hole():\n",
        "    pipe_od = 12\n",
        "    pipe_id = 10\n",
        "    seg_length = 30\n",
        "\n",
        "    outer = Cy(r=pipe_od, h=seg_length, center=True)\n",
        "    inner = Cy(r=pipe_id, h=seg_length + 2, center=True)\n",
        "    pipe_a = outer - inner\n",
        "\n",
        "    pipe_b = rotate(a=90, v=FORWARD_VEC)(pipe_a)\n",
        "    # pipe_a and pipe_b are both hollow, but because\n",
        "    # their central voids aren't explicitly holes,\n",
        "    # the union of both pipes has unwanted internal walls\n",
        "    # 没有用hole()就是这个结果\n",
        "\n",
        "    return pipe_a + pipe_b\n",
        "\n",
        "r.render(pipe_intersection_no_hole())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BQo4XQgirM3b",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "- 当我们需要在hole()所形成的负空间里插入一个物体时，我们需要用到另一个函数part()，以消除负空间，看看下面这个例子："
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "d9ww4dWerM3k",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def multipart_hole():\n",
        "    # It's good to be able to keep holes empty, but often we want to put\n",
        "    # things (bolts, etc.) in them.  The way to do this is to declare the\n",
        "    # object containing the hole a \"part\".  Then, the hole will remain\n",
        "    # empty no matter what you add to the 'part'.  But if you put an object\n",
        "    # that is NOT part of the 'part' into the hole, it will still appear.\n",
        "\n",
        "    # On the left (not_part), here's what happens if we try to put an object\n",
        "    # into an explicit hole:  the object gets erased by the hole.\n",
        "\n",
        "    # On the Tx (is_part), we mark the Cu-with-hole as a \"part\",\n",
        "    # and then insert the same 'bolt' Cy into it.  The entire\n",
        "    # bolt rematins.\n",
        "\n",
        "    b = Cu(10, center=True)\n",
        "    c = Cy(r=2, h=12, center=True)\n",
        "\n",
        "    # A Cu with an explicit hole\n",
        "    not_part = b - hole()(c)\n",
        "\n",
        "    # Mark this Cu-with-hole as a separate part from the Cy\n",
        "    is_part = part()(not_part.copy())\n",
        "\n",
        "    # This fits in the holes\n",
        "    bolt = Cy(r=1.5, h=14, center=True) + Tz(8)(Cy(r=2.5, h=2.5, center=True))\n",
        "\n",
        "    # The section of the bolt inside not_part disappears.  The section\n",
        "    # of the bolt inside is_part is still there.\n",
        "    a = not_part + bolt + Tx(45)(is_part + bolt)\n",
        "\n",
        "    return a\n",
        "\n",
        "if __name__ == '__main__':\n",
        "    out_dir = sys.argv[1] if len(sys.argv) > 1 else os.curdir\n",
        "    file_out = os.path.join(out_dir, 'hole_example.scad')\n",
        "\n",
        "    # On the left, pipes with no explicit holes, which can give\n",
        "    # unexpected walls where we don't want them.\n",
        "    # On the Tx, we use the hole() function to fix the problem\n",
        "    a = pipe_intersection_no_hole() + Tx(45)(pipe_intersection_hole())\n",
        "\n",
        "    # Below is an example of how to put objects into holes and have them\n",
        "    # still appear\n",
        "    b = up(40)(multipart_hole())\n",
        "    a += b\n",
        "\n",
        "    # print(\"%(__file__)s: SCAD file written to: \\n%(file_out)s\" % vars())\n",
        "    # scad_render_to_file(a, file_out, file_header='$fn = %s;' % SEGMENTS, include_orig_code=True)\n",
        "    \n",
        "r.render(multipart_hole())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4B4T2c8JrM30",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "    b = Cu(10, center=True)\n",
        "    c = Cy(r=2, h=12, center=True)\n",
        "\n",
        "    # A Cu with an explicit hole\n",
        "    not_part = b - hole()(c)\n",
        "\n",
        "    # Mark this Cu-with-hole as a separate part from the Cy\n",
        "    is_part = part()(not_part.copy())\n",
        "\n",
        "    # This fits in the holes\n",
        "    bolt = Cy(r=1.5, h=14, center=True) + Tz(8)(Cy(r=2.5, h=2.5, center=True))\n",
        "\n",
        "    # The section of the bolt inside not_part disappears.  The section\n",
        "    # of the bolt inside is_part is still there.\n",
        "    a = not_part + bolt + Tx(45)(is_part + bolt)\n",
        "    \n",
        "    r.render(a)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FWTETGkOrM4Q",
        "colab_type": "text"
      },
      "source": [
        "* 接下来根据作者的arc()函数，做一个Sec()函数(已经加到了utils,py)："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LtzzD177rM4V",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def Sec1(rad = 10, start_degrees = 15, end_degrees = 165, thick = 5, segments= 60):\n",
        "    # Note: the circle that this arc is drawn from gets segments,\n",
        "    # not the arc itself.  That means a quarter-circle arc will\n",
        "    # have segments/4 segments.\n",
        "    # 加上了厚度thick\n",
        "\n",
        "    bottom_half_square = Ty(-rad)(Sq([3 * rad, 2 * rad], center=True))\n",
        "    top_half_square = Ty(rad)(Sq([3 * rad, 2 * rad], center=True))\n",
        "\n",
        "    start_shape = Ci(rad, segments=segments)\n",
        "\n",
        "    if abs((end_degrees - start_degrees) % 360) <= 180:\n",
        "        end_angle = end_degrees - 180\n",
        "        ret = start_shape\n",
        "        ret -= Rz(start_degrees)(bottom_half_square.copy())\n",
        "        ret -= Rz(end_angle)(bottom_half_square.copy())\n",
        "    else:\n",
        "        ret = start_shape\n",
        "        ret *= Rz(start_degrees)(top_half_square.copy()) + Rz(end_degrees)(bottom_half_square.copy())\n",
        "        \n",
        "        \n",
        "    return Le(thick)(ret)        "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "scrolled": true,
        "id": "K-NrUNPJrM4d",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "    d = Sec1()\n",
        "    r.render(d)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1VJXIkt6rM4n",
        "colab_type": "text"
      },
      "source": [
        "* 关于offset函数，首先看看openscad里的这个函数："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WqyYa-YmrM4p",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "c = Of (delta = 2)(Sq(10)) -Sq(10)\n",
        "c += Tx(15)(Of (2)(Sq(10)) -Sq(10))\n",
        "\n",
        "r.render(Le(3)(c))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OkmwyQH9rM4y",
        "colab_type": "text"
      },
      "source": [
        "* 作者也做了一个这样的函数，有啥不同呢？ 这里存疑。。。。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uo71Ar-drM42",
        "colab_type": "code",
        "colab": {},
        "outputId": "2772fd59-4d6d-4664-84a9-248b7b1e1a45"
      },
      "source": [
        "r.render(_parallel_seg())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "NameError",
          "evalue": "name '_parallel_seg' is not defined",
          "traceback": [
            "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[1;32m<ipython-input-12-f66b6fd26c8e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_parallel_seg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[1;31mNameError\u001b[0m: name '_parallel_seg' is not defined"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DlTUcGuqrM5I",
        "colab_type": "code",
        "colab": {},
        "outputId": "d98c960f-4841-49c7-9cc4-d77fe409cf5c"
      },
      "source": [
        "r.render(offset_points(0, offset))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "TypeError",
          "evalue": "'int' object is not subscriptable",
          "traceback": [
            "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[1;32m<ipython-input-15-3d6d92d3f13b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0moffset_points\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moffset\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[1;32mI:\\ProgramData\\Anaconda3\\lib\\site-packages\\solid\\utils.py\u001b[0m in \u001b[0;36moffset_points\u001b[1;34m(point_arr, offset, inside, closed_poly)\u001b[0m\n\u001b[0;32m    951\u001b[0m         \u001b[1;31m# Using the first three points in point_arr, figure out which direction\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    952\u001b[0m         \u001b[1;31m# is inside and what plane to put the points in\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 953\u001b[1;33m         \u001b[0mpoint_arr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0meuclidify\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpoint_arr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mPoint3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    954\u001b[0m         \u001b[0min_dir\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0m_inside_direction\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0mpoint_arr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    955\u001b[0m         \u001b[0mnormal\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0m_three_point_normal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0mpoint_arr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
            "\u001b[1;31mTypeError\u001b[0m: 'int' object is not subscriptable"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "S7FGjmusrM5X",
        "colab_type": "text"
      },
      "source": [
        "* 先看一下那个螺丝函数"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "scrolled": true,
        "id": "vIHaK4QurM5Z",
        "colab_type": "code",
        "colab": {},
        "outputId": "5cbe6759-6a32-4ed8-e972-7db335e04477"
      },
      "source": [
        "from solid import screw_thread\n",
        "\n",
        "r.render(thread(pts, inner_rad=10, pitch=6, length=2, segments_per_rot=31,\n",
        "               neck_in_degrees=30, neck_out_degrees=30))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "NameError",
          "evalue": "name 'thread' is not defined",
          "traceback": [
            "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[1;32m<ipython-input-25-8460ac3e8a70>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0msolid\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mscrew_thread\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m r.render(thread(pts, inner_rad=10, pitch=6, length=2, segments_per_rot=31,\n\u001b[0m\u001b[0;32m      4\u001b[0m                neck_in_degrees=30, neck_out_degrees=30))\n",
            "\u001b[1;31mNameError\u001b[0m: name 'thread' is not defined"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tjoxj5zJrM5p",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}